<template>
  <el-container style="height: 100vh" class="">
    <el-header class="head fixed-heade">
      <div></div>
      <!-- <el-page-header @back="goBack" title="" content=""></el-page-header> -->
      <!-- 2個下拉框都綁定的一個 -->
      <el-select
        v-model="inputMessage"
        placeholder="请选择热门查询"
        class="custom-select"
        style="width: 400px"
      >
        <el-option
          v-for="item in topList"
          :key="item"
          :label="item"
          :value="item"
        ></el-option>
      </el-select>
      <el-dropdown class="setting-dropdown">
        <el-button
          round
          class="setting-button"
          style="font-family: 'Microsoft YaHei'; font-size: 15px"
        >
          设置
          <i class="el-icon-arrow-down el-icon--right"></i>
        </el-button>
        <el-dropdown-menu slot="dropdown">
          <el-dropdown-item>清空聊天框</el-dropdown-item>
          <el-dropdown-item>切换查询销量</el-dropdown-item>
          <el-dropdown-item>切换查询客户</el-dropdown-item>
        </el-dropdown-menu>
      </el-dropdown>
    </el-header>
    <el-container>
      <el-aside width="450px" class="aside">
        <!-- 常规查询案例的下拉框 -->
        <select class="display" v-model="inputMessage" style="width: 80%">
          <!-- :label="item.content" -->
          <option disabled value="">
            &nbsp;&nbsp;请选择你需要查询的销量场景
          </option>
          <option
            v-for="(item, index) in caseList"
            :key="index"
            :value="item.content"
          >
            {{ item.content }}
          </option>
        </select>
        <!-- 客户筛选案例中的下拉框 -->
        <select class="display" v-model="inputMessage" style="width: 80%">
          <option disabled value="" selected>
            &nbsp;&nbsp;请选择客户筛选场景
          </option>
          <!-- :label="item.content" -->
          <option
            v-for="(item, index) in customerList"
            :key="index"
            :value="item.content"
          >
            {{ item.content }}
          </option>
        </select>
        <el-popover placement="right" width="400" trigger="click">
          <div style="margin-top: 10px; border-radius: 5px">
            <!-- 如果 SQL 数组为空，显示提示信息，否则遍历展示每条 SQL 语句 -->
            <div v-if="sqlList.length === 0">这里展示 SQL 语句</div>
            <div v-else>
              <p v-for="(sql, index) in sqlList" :key="index">
                {{ sql }}
              </p>
            </div>
          </div>
          <el-button slot="reference">查看SQL语句</el-button>
        </el-popover>
        <!-- 子图展示 -->
        <div class="graph">
          <Graph
            :key="graphKey"
            ref="graphRef"
            :nodes="graph_list.nodes"
            :edges="graph_list.edges"
          ></Graph>
        </div>
        <!-- <div>
          <el-button
            type="primary"
            @click="handle_get_graph()"
            :loading="is_graph_loading"
            >获取子图</el-button
          >
          <el-button @click="handleStartTask()">test</el-button>
        </div> -->
      </el-aside>
      <el-container>
        <el-main
          id="main-content"
          style="padding: 20px"
          class="scrollable-main scrollable-content"
        >
          <div class="main-content" ref="scrollBox">
            <!-- 聊天信息主体 -->
            <div class="content">
              <div class="content-info">
                <div class="content-list">
                  <!-- Fixed opening message -->
                  <div class="content-li">
                    <div class="left-info">
                      <img :src="head.server" class="myhead" />
                      <div class="myinfo">
                        <div class="greeting">
                          <span
                            >欢迎使用本系统！请选择一个选项查看详细信息。在顶端导航栏的下拉框中可以选择对应的热门查询
                          </span>
                        </div>
                      </div>
                    </div>
                  </div>
                  <div
                    class="content-li"
                    v-for="(item, index) in infoList"
                    :key="index"
                  >
                    <!-- Right side -->
                    <div v-if="item.role === 'self'" class="right-info">
                      <img class="myhead" :src="head.self" />
                      <span class="myinfo">{{ item.content }}</span>
                    </div>
                    <!-- Left side -->
                    <div v-else class="left-info">
                      <img class="myhead" :src="head.server" />
                      <!-- 文字 -->
                      <span v-if="item.type === 'text'" class="myinfo">{{
                        item.content
                      }}</span>
                      <!-- 表格 -->
                      <div v-else class="myinfo">
                        <!-- Show/hide SQL 暂时将代码放在这后期移除-->
                        <div v-if="false && item.hasSQL">
                          <button
                            @click="showSql(index)"
                            class="toggle-button"
                            size="mini"
                          >
                            {{ item.isShowSQL ? "显示内容" : "隐藏内容" }}
                          </button>
                          <div v-show="!item.isShowSQL" class="sql-text">
                            <span v-text="item.sqlString"></span>
                          </div>
                        </div>
                        <!-- 表格组件-常规查询 -->
                        <div v-if="item.tableType === 'type1'">
                          <ve-table
                            :columns="item.columns"
                            :table-data="item.tableData"
                            :cell-span-option="cellSpanOption"
                            border-y
                          />
                          <div
                            v-show="item.tableData.length == 0"
                            class="empty-data"
                          >
                            暂无数据
                          </div>
                        </div>
                        <!--表格组件2-客户筛选  -->
                        <div v-if="item.tableType === 'type2'">
                          <CustomQuery :rowData="item.tableData"></CustomQuery>
                        </div>
                      </div>
                      <div
                        v-if="item.tableType === 'type1'"
                        class="reply-container"
                      >
                        <!-- 这里放置回复组件 -->
                        <RelationObject
                          :question="item.content"
                          @send-message="handleSendMessage"
                        ></RelationObject>
                      </div>
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </el-main>
        <el-footer class="fixed-footer">
          <!-- 语言输入 -->
          <div class="voice-input-button-wrapper">
            <voice-input-button
              v-model="inputMessage"
              @record="showResult"
              @record-start="recordStart"
              @record-stop="recordStop"
              @record-blank="recordNoResult"
              @record-failed="recordFailed"
              @record-ready="recordReady"
              @record-complete="recordComplete"
              interactiveMode="touch"
              color="#fff"
              tipPosition="top"
              returnMode="complete"
            >
              <template slot="no-speak">没听清您说的什么</template>
            </voice-input-button>
          </div>
          <el-button @click="continueQuery" round>继续查询</el-button>
          <el-button @click="startNewQuery" round>开启新查询</el-button>
          <!-- 输入框 -->
          <div class="input-area">
            <el-input
              rounded-input
              v-model="inputMessage"
              placeholder="请输入内容"
              @keyup.enter="sendMessage"
            >
              <template #suffix>
                <el-button
                  round
                  type="primary"
                  style="height: 40px"
                  @click="sendMessage"
                  >发送</el-button
                >
              </template>
            </el-input>
          </div>
        </el-footer>
      </el-container>
    </el-container>
  </el-container>

</template>
  

  <script>
import { formatNumberArray } from "@/utils/utils.js";
import RelationObject from "../components/RelationObject.vue";
import CustomQuery from "@/components/CustomQuery.vue";
// 导入表头配置文件
import { labelConfig } from "@/utils/lableConfig.js";
import Graph from "../components/Graph.vue";
export default {
  //引入组件
  name: "main_chat",
  // 注册组件
  components: {
    Graph,
    RelationObject,
    CustomQuery,
  },
  data() {
    return {
      //===========================?
      // todo:子图临时，后期可删
      is_graph_loading: false,
      graphKey: 0, //初始化 key
      inputMessage: "",  // 当前用户输入的消息
      OldMessage: "",    // 旧的查询消息，用于叠加
      NewMessage: "",    // 上一次的查询消息
      aa:[],
      temp_graph: "",
      // 回复表格中猜你想问的数据
      Relationmessages: [
        {
          title: "关联查询",
          message: "沙市营销部2022年产量",
        },
        {
          title: "关联查询",
          message: "沙市营销部2023年产量",
        },
        {
          title: "关联查询",
          message: "沙市营销部2024年产量",
        },
      ],
      // 表格合并
      cellSpanOption: {
        bodyCellSpan: this.bodyCellSpan,
      },
      // 前端展示子图的数据
      graph_list: {
        nodes: [
          { id: "node1", label: "Node 1" },
          { id: "root", label: "Node 2" },
          { id: "node3", label: "Node 3" },
        ],
        edges: [
          { source: "root", target: "node1", label: "Edge Label 1" },
          { source: "root", target: "node3", label: "Edge Label 2" },
        ],
      },
      topList: [], //查询最多的例子
      showEmpty: false,
      scrollHeight: 0,
      scrollTop: 0,
      pageType: "0",
      showSelectTable: false,
      infoList: [],
      infoList_2: [
        {
          role: "server",
          content: "欢迎来到客户筛选，请问有什么我可以帮助您的？",
          type: "text",
        },
        {
          content: "请问荆州市局沙市营销部在2024年3月的总销售量是多少？",
          columns: [
            {
              field: "sku_id",
              key: "a",
              title: "SKU ID",
              align: "center",
            },
            {
              field: "product_name",
              key: "b",
              // width: 200,
              title: "产品名称",
              align: "center",
            },
            {
              field: "order_qty",
              key: "c",
              title: "订单数量",
              align: "left",
            },
          ],
          tableData: [
            {
              sku_id: "1001",
              product_name: "黄鹤楼（软蓝）",
              order_qty: 100,
            },
            {
              sku_id: "1002",
              product_name: "黄鹤楼（硬蓝）",
              order_qty: 150,
            },
            {
              sku_id: "1003",
              product_name: "黄鹤楼（软红）",
              order_qty: 200,
            },
            {
              sku_id: "1004",
              product_name: "黄鹤楼（硬红）",
              order_qty: 250,
            },
            {
              sku_id: "1005",
              product_name: "黄鹤楼（软黄）",
              order_qty: 300,
            },
          ],
          type: "table",
          msg: "暂无数据",
          // 是否有sql,和是否展示sql
          hasSQL: true,
          isShowSQL: false,
          sqlString: "SELECT * FORM",
        },
        {
          content: "模拟数据123模拟数据123模拟数据123模拟数据123",
          type: "text",
        },
      ],
      // 临时的sql数组
      sqlList: [
        "SELECT * FROM users WHERE id = 1;",
        "UPDATE users SET name = 'John' WHERE id = 2;",
        "DELETE FROM orders WHERE order_id = 100;",
      ],
      //头像
      head: {
        server: require("../assets/head.jpg"),
        self: require("../assets/test.png"),
      },
      showSelectTable: false, // 控制表格显示与隐藏
      // 案例列表
      caseList: [
        {
          title: "销量",
          content: "查询沙市营销部各市场部2024年4月的销量及单箱均价",
        },
        {
          title: "销量",
          content: "查询沙市营销部2024年4月销量",
        },
        {
          title: "销量",
          content: "查询全市2024年4月分类别卷烟销量",
        },
        {
          title: "销量",
          content: " 查询全市2024年4月低价位销量及占比",
        },
        {
          title: "销量",
          content: " 查询全市2024年4月低焦油销量及占比",
        },
        {
          title: "销量",
          content: " 查询全市2024年4月共育品规销量及占比",
        },
        {
          title: "销量",
          content: " 查询全市2024年4月创新品规销量及占比",
        },
        {
          title: "明细查询",
          content: "@查询低价位中各品牌香烟的销量",
        },
        {
          title: "销量",
          content: "@查询沙市区营销部的销量",
        },
        {
          title: "销量",
          content: "@查询沙市营销部各市场部的销量及单箱均价",
        },
        {
          title: "销量",
          content: "@查询全市重点品牌销量占所有品牌的占比",
        },
        {
          title: "销量",
          content: "@查询全市烤烟销量及占比",
        },
        {
          title: "销量",
          content: "@高希霸(特冠木盒25支装)的销量",
        },
        {
          title: "销量",
          content: "@查询全市2024年4月分类别卷烟的单箱均价",
        },
        {
          title: "销量",
          content: "@查询全市重点品牌的销量",
        },
        {
          title: "销量",
          content: "@查询全市低价位的销量",
        },
        {
          title: "销量",
          content: "@查询全市低焦油的销量",
        },
        {
          title: "销量",
          content: "@查询全市共育品规的销量",
        },
        {
          title: "销量",
          content: "@查询沙市区营销部2024年4月一类香烟的销量（一类..的处理）",
        },
        {
          title: "销量",
          content: "@查询松滋重点品规的总销量（地名松滋的识别问题）",
        },
        {
          title: "销量",
          content: "@查询沙市建牌混合型重点品规的平均销量（识别问题）",
        },
        {
          title: "销量",
          content: "@查询松滋中式混合高端卷烟的各品牌香烟的销量（识别问题）",
        },
        {
          title: "销量",
          content: "@查询沙市低价位雪茄的各品牌的销量（开发中....）",
        },
        {
          title: "销量",
          content: "@查询沙市高价位(机制/手工)雪茄的单箱均价(开发中...)",
        },
        {
          title: "销量",
          content: "@查询沙市行业共育品规香烟的单箱均价",
        },
        {
          title: "销量",
          content: "@查询沙市黄鹤楼的平均日销量(单品规平均销量.....)",
        },
        {
          title: "销量",
          content: "@查询沙市中式混合型卷烟的总销量(中式混合型卷烟.....)",
        },
        {
          title: "销量",
          content: "@查询手工雪茄烟的总销量(识别机制雪茄以及手工雪茄.....)",
        },
        {
          title: "销量",
          content: "@",
        },
        // 可以根据需要添加更多案例
      ],
      // 客户筛选的案例
      customerList: [
        {
          title: "客户",
          content: "$表格筛选",
        },
        {
          title: "客户",
          content: "$查询2024年查询销量多于10的客户信息及销量",
        },
        {
          title: "客户",
          content: "$查询过去3年内有违法违规的客户信息",
        },
        {
          title: "客户",
          content: "$查询是连锁店且不是夜店的客户信息",
        },
        {
          title: "客户",
          content: "$查询有黄鹤楼订单的客户信息",
        },
      ],
      //===========================?
      inputMessage: "",
      //   聊天页面的消息
      messages: [
        {
          content: "请问荆州市局沙市营销部在2024年3月的总销售量是多少？",
          columns: [
            {
              field: "sku_id",
              key: "a",
              title: "SKU ID",
              align: "center",
            },
            {
              field: "product_name",
              key: "b",
              // width: 200,
              title: "产品名称",
              align: "center",
            },
            {
              field: "order_qty",
              key: "c",
              title: "订单数量",
              align: "left",
            },
          ],
          tableData: [
            {
              sku_id: "1001",
              product_name: "黄鹤楼（软蓝）",
              order_qty: 100,
            },
            {
              sku_id: "1002",
              product_name: "黄鹤楼（硬蓝）",
              order_qty: 150,
            },
            {
              sku_id: "1003",
              product_name: "黄鹤楼（软红）",
              order_qty: 200,
            },
            {
              sku_id: "1004",
              product_name: "黄鹤楼（硬红）",
              order_qty: 250,
            },
            {
              sku_id: "1005",
              product_name: "黄鹤楼（软黄）",
              order_qty: 300,
            },
          ],
          type: "table",
          username: "张三",
          position: "left",
          msg: "暂无数据",
          // 是否有sql,和是否展示sql
          hasSQL: true,
          isShowSQL: false,
          sqlString: "SELECT * FORM",
          //   后面添加
          sender: false,
          isCustomResponse: false,
        },
      ],
      hasShownIntro: false,
      selectedSql: "",
      sqlStatements: [
        { key: "1", value: "SELECT * FROM table1" },
        // 其他 SQL 语句
      ],
    };
  },
  // 构子函数
  created() {
    this.getTopList();
  },
  mounted() {
    this.scrollHeight = window.innerHeight;
    if (!this.hasShownIntro) {
      this.messages.push({
        sender: false,
        content: "欢迎使用本系统！请选择输入您要查看的信息。",
        isCustomResponse: false,
      });
      this.hasShownIntro = true;
    }
  },

  methods: {
    //正则匹配
    checkContinue(str) {
      const regex = /继续|接着|然后|再/;  
      return regex.test(str);
    },
  //判断是否新查询
  handleQuery() {
  try {
    // 如果消息包含“继续”等关键字，则继续查询。
    if (this.checkContinue(this.inputMessage)) {
      this.continueQuery();
      console.log("continueQuery");
    } else {
      // 开始新的查询
      this.startNewQuery();
      console.log("startNewQuery");
    }

    // 继续将消息发送到后端
    this.NewMessage += "" + this.inputMessage; // 为后续查询拼接
    this.handler_3(this.NewMessage); // 调用 handler_3 获取后端数据
  } catch (error) {
    console.error("Query Error:", error);
    this.$message({
      message: "处理查询时发生错误，请稍后再试。",
      type: "error",
    });
  }
},

      //继续查询
      continueQuery() {
      if (this.inputMessage.trim()) {
        // 将当前输入的消息与上次查询的消息拼接 


      }
    },
      // 开始新查询
     startNewQuery() {
     //清空其他记录消息
      this.NewMessage = "";
      this.OldMessage = "";
    },
    /**
     * 表格变成图
     * @param tableData
     * @param key_word 中心结点的lable
     */
    tableToGraph(tableData, key_word) {
      // 构造节点数据
      const nodes = tableData.map((row, index) => {
        // 动态选择一个字段作为 label，取第一个非空字段
        const values = Object.values(row);
        const label =
          row.org_name || row.brand_name || values[1] || `Node ${index + 1}`; // 默认命名

        // 返回节点，所有字段作为属性存储
        return {
          id: `node${index + 1}`, // 节点唯一ID
          label: label, // 节点的展示标签
          data: row, // 所有字段作为节点属性存储
        };
      });

      // 添加根节点
      nodes.push({
        id: "root", // 根节点唯一ID
        label: key_word, // 根节点标签
      });

      // 构造边数据（每个节点都连接到根节点）
      const edges = tableData.map((row, index) => ({
        source: "root", // 根节点作为边的起点
        target: `node${index + 1}`, // 当前节点作为边的终点
      }));

      // 返回节点和边
      return { nodes, edges };
    },
    // 调用子组件方法
    refreshGraph() {
      if (this.$refs.graphRef) {
        this.$refs.graphRef.updateGraphData();
      }
      this.graphKey += 1; // 更新 key，强制重载组件
    },
    // body cell span，合并表格
    bodyCellSpan({ row, column, rowIndex }) {
      if (column.field === "key_word") {
        if (rowIndex === 0) {
          return {
            rowspan: row.length || 100,
            colspan: 1,
          };
        }
        // does not need to be rendered
        else if (rowIndex != 0) {
          return {
            rowspan: 0,
            colspan: 0,
          };
        }
      }
    },

    handleSendMessage(item) {
      // 处理子组件发送的消息
      console.log("发送消息:", item);
      this.inputMessage = item.message;
    },

    //滚动条默认滚动到最底部
    scrollToBottom(s, c) {
      const mainContent = document.getElementById("main-content");
      // console.log(mainContent);
      mainContent.scrollTop =
        mainContent.scrollHeight - mainContent.clientHeight + 10;
    },
    toggleTable() {
      this.showSelectTable = !this.showSelectTable;
    },

    showSql(index) {
      this.$set(
        this.infoList[index],
        "isShowSQL",
        !this.infoList[index].isShowSQL
      );
    },
    handleScroll(event) {
      this.scrollTop = event.target.scrollTop;
    },
    // ====================2024.11.2=======================
    // 发送异步请求
    async handleStartTask(msg = "查询沙市营销部各市场部的销量及单箱均价") {
      try {
        // 启动任务并获取任务id
        const response = await this.$axios({
          url: "http://localhost:5000/submit",
          method: "post",
          data: { input: msg },
        });
        const result_id = response.data.data.result_id;
        // 开始轮训任务
        setTimeout(() => {
          this.pollTaskResult(result_id);
        }, 1000);
      } catch (error) {
        this.$message({
          message: "Failed to start task",
          type: "error",
        });
        console.error("Failed to start task:", error);
      }
    },
    /**
     * 根据result_id开始轮训任务。
     * @param taskId 任务id
     * @param retryCount 第几轮
     * @param maxRetries 最大轮训次数
     */
    async pollTaskResult(taskId, retryCount = 0, maxRetries = 10) {
      try {
        const response = await this.$axios({
          url: "http://localhost:5000//result/" + taskId,
          method: "get",
        });
        const data = response.data;
        // 数据处理
        if (data.Code == 200 || data.message == "Success") {
          // console.log("查询的数据：", data);
          // 正确数据
          this.process_sub_res(data, this.inputMessage);
        } else if (data.Code == 404 || data.message == "Not Found") {
          // 失败的情况
          // 如果任务尚未完成，检查是否已达最大重试次数
          if (retryCount < maxRetries) {
            // 如果任务尚未完成，等待 1 秒后再次请求
            setTimeout(
              () => this.pollTaskResult(taskId, retryCount + 1, maxRetries),
              1000
            );
          } else {
            this.$message({
              message: "任务超时，请稍后重试",
              type: "warning",
            });
            console.warn("任务超时，已停止轮询");
          }
        } else if (
          data.Code == 403 ||
          data.message == "Pending" ||
          typeof data.data === "string"
        ) {
          // 如果任务尚未完成，检查是否已达最大重试次数
          if (retryCount < maxRetries) {
            // 如果任务尚未完成，等待 1 秒后再次请求
            setTimeout(
              () => this.pollTaskResult(taskId, retryCount + 1, maxRetries),
              1000
            );
          } else {
            this.$message({
              message: "任务超时，请稍后重试",
              type: "warning",
            });
            console.warn("任务超时，已停止轮询");
          }
        }
      } catch (error) {
        this.$message({
          message: "网络连接超时",
          type: "error",
        });
        console.error("Failed to get task result:", error);
      }
    },
    // ======================2024.11.2=====================
    /**
     * 向后端发送请求获取‘猜你想问’的数据
     * @param msg 问询消息
     */
    async handle_get_similar_query(msg) {
      try {
        const response = await this.$axios({
          url: "http://121.41.97.114:5001/similar_query",
          method: "POST",
          timeout: 50000,
          data: {
            input: msg,
          },
          headers: {
            "Content-Type": "application/json",
          },
        });
        console.log("猜你想问-1", response);

        if (response.data.Code === 200 && response.data.data.length > 0) {
          const originalData = response.data.data;
          console.log("猜你想问-2", originalData);

          const formattedData = originalData.map((item) => ({
            title: "关联查询",
            message: item[0],
          }));

          return formattedData;
        } else {
          console.error("请求失败(猜你想问的数据)", response.data.message);
          this.$message({
            message: response.data.message,
            type: "warning",
            duration: 2000,
          });
          return [{ title: "关联查询", message: "暂无数据" }];
        }
      } catch (error) {
        console.error("网络错误(猜你想问)", error);
        return [{ title: "关联查询", message: "暂无数据" }];
      }
    },
    /**
     * 向后端请求知识图谱子图数据
     *  @param msg 问询消息
     */
    handle_get_graph(msg) {
      // 前提判断：msg 和 this.temp_graph 至少有一个不为空的字符串
      if (
        (!msg || msg.trim() === "") &&
        (!this.temp_graph || this.temp_graph.trim() === "")
      ) {
        this.$message({
          message: "先发送一个请求先",
          type: "warning",
        });
        return; // 提前返回，停止后续操作
      }
      this.is_graph_loading = true;
      this.$axios({
        url: "http://121.41.97.114:5001/graph",
        method: "POST",
        // 5s
        timeout: 5000,
        data: {
          input: this.temp_graph || msg,
        },
        headers: {
          "Content-Type": "application/json",
        },
      })
        .then((res) => {
          console.log("子图-1：", res);
          if (res.data.Code === 200 && res.data.data) {
            // 原始数据
            const originalData = res.data.data;
            console.log("子图-2：", originalData);
            this.graph_list.nodes = originalData.nodes;
            this.graph_list.edges = originalData.edges;
            this.graphKey += 1; // 更新 key，强制重载组件
          } else {
            // 如果数据为空或请求失败，返回默认数据
            console.error("请求失败(子图)", res.data.message);
            this.$message({
              message: "子图数据为空",
              type: "warning",
              duration: 4000,
            });
          }
        })
        .catch((error) => {
          console.error("网络错误（子图）", error);
          this.$message({
            message: "子图请求错误失败！！！",
            type: "warning",
            duration: 2000,
          });
        })
        .finally(() => {
          this.is_graph_loading = false;
        });
    },
    //
    handler1(msg) {
      console.log("msg:", msg); // 检查 msg 是否有正确的值

      this.$axios({
        url: "http://127.0.0.1:5000/submit",
        method: "POST",
        // 10s
        timeout: 20000,
        data: {
          input: msg,
        },
        headers: {
          "Content-Type": "application/json",
        },
      })
        .then((response) => {
          console.log(response);
          console.log("Request success, msg is:", msg);
          const data = response.data;
          if (
            data.code !== 200 ||
            data.code === undefined ||
            typeof data.data === "string"
          ) {
            this.$message({
              message: "无法理解...",
              type: "warning",
              duration: 2000,
            });
          } else {
            const row = data.data;
            const tableHeader = this.processTableData(row, msg);
            console.log("表头：", tableHeader);
            const sql_list = data.sql_list;
            //
            this.sqlList = sql_list;
            const sqlString = sql_list.join("\n");
            const tableData = formatNumberArray(row);
            this.addTableToChat({
              tableHeader: tableHeader,
              row: tableData,
              role: "机器人",
              sql: sqlString,
            });
          }
        })
        .catch((error) => {
          this.$message({
            message: "网络连接超时，请联系管理员",
            type: "error",
          });
          console.error(error);
          console.log("请求超时");
        });
    },
    // 发送后端请求
    handler_3(msg) {
      this.$axios({
        url: "http://121.41.97.114:5000/submit",
        method: "POST",
        timeout: 10000,
        data: {
          input: msg,
        },
        headers: {
          "Content-Type": "application/json",
        },
      })
        .then((response) => {
          const data = response.data;
          if (
            data.Code !== 200 ||
            data.Code === undefined ||
            typeof data.data === "string"
          ) {
            this.$message({
              message: "无法理解...",
              type: "warning",
              duration: 2000,
            });
          } else {
             console.log("2222",response)
            const tableData=response.data.data.result[0]
            console.log("3333",tableData)
            // 数据处理 todo
            this.addTableToChat({ row: tableData, role: "机器人", tableType: "type2" });
          }
        })
        .catch((error) => {
          this.$message({
            message: "网络连接超时，请联系管理员",
            type: "error",
          });
          console.error(error);
          console.log("请求超时");
        });
    },
    // 发送后端请求
    handler_2(msg) {
      this.$axios({
        url: "http://121.41.97.114:5001/submit",
        method: "POST",
        timeout: 10000,
        data: {
          input: msg,
        },
        headers: {
          "Content-Type": "application/json",
        },
      })
        .then((response) => {
          const data = response.data;
          if (
            data.Code !== 200 ||
            data.Code === undefined ||
            typeof data.data === "string"
          ) {
            this.$message({
              message: "无法理解...",
              type: "warning",
              duration: 2000,
            });
          } else {
            // 数据处理
            const result = data.data;
            const row = result.result;
            const tableHeader = this.processTableData(result.result, msg);
            console.log("表头：", tableHeader);
            const sql_list = result.sql_list;
            //
            this.sqlList = sql_list;
            const sqlString = sql_list.join("\n");
            // 对于numbuer，统一保留小数点后2位
            const tableData = formatNumberArray(row);
            // 直接添加
            // 表头和数据中添加上下文信息 unshift/push
            tableHeader.unshift({
              field: "key_word",
              key: "key_word",
              title: "查询场景",
              align: "center",
            });
            // 为每个对象添加 key_word
            const key_word = result.keyword_array;
            // 获取所有表头的 title 字段值，形成一个数组
            const titleArray = tableHeader.map((header) => header.title);
            // 过滤掉 keyword_array 中已经在 titleArray 中的关键字
            const filteredKeywords = key_word.filter(
              (keyword) => !titleArray.includes(keyword)
            );
            // ======================
            // 根据表格数据装换位图数据
            const graph = this.tableToGraph(tableData, filteredKeywords);
            console.log("图数据", graph);
            this.graph_list = graph;
            this.graphKey += 1; //强制刷新组件
            // ======================
            // 表格数据补充
            tableData.forEach((item) => {
              item.key_word = filteredKeywords.join(",");
            });
            console.log("表格数据", tableData);
            console.log("表格表头", tableHeader);
            this.addTableToChat({
              tableHeader: tableHeader,
              row: tableData,
              role: "机器人",
              sql: sqlString,
              msg: msg,
            });
          }
        })
        .catch((error) => {
          this.$message({
            message: "网络连接超时，请联系管理员",
            type: "error",
          });
          console.error(error);
          console.log("请求超时");
        });
    },
    //获取表头数据
    processTableData(data, userQuery = "") {
      if (data.length === 0) {
        return [];
      }
      const allKeys = Object.keys(data[0]);
      // 根据用户查询对键进行排序
      const sortedKeys = this.sortKeysByUserQuery(allKeys, userQuery);
      // 使用 Set 来确保不会有重复的 prop
      const uniqueKeys = [...new Set(sortedKeys)];
      const tableHeader = uniqueKeys.map((key) => ({
        field: key,
        key: String(key),
        // width: 200,
        title: this.getLabelForKey(key, userQuery),
        // title: this.capitalize(key),
        align: "center",
      }));
      return tableHeader;
    },
    // 表格lable 英文转中文
    capitalize(str) {
      const specialCases = {
        org_name: "部门",
        average_price_per_box: "单箱均价",
        sales_volume: "销量",
        proportion: "占比（%）",
        cig_grade: "分类别卷烟",
        total_sales_volume: "总销量",
        custname:"客户姓名",
      };

      if (specialCases[str]) {
        return specialCases[str];
      }
      return str
        .replace(/_/g, " ")
        .replace(/\b\w/g, (char) => char.toUpperCase());
    },

    getLabelForKey(key, userQuery) {
      const config = labelConfig[key];
      if (!config) {
        // 如果配置中没有该键，返回原始键名
        return key;
      }
      const matchedSynonym = config.synonyms.find((synonym) =>
        userQuery.includes(synonym)
      );
      return matchedSynonym || config.default;
    },
    /**
     * sortKeysByUserQuery 函数:
     * 这个函数负责根据用户查询中关键词的顺序对字段进行排序。
     * 它首先创建一个映射，将所有可能的中文标签（包括同义词）映射到对应的键。
     * 然后，它在用户查询中查找这些标签，并按照它们在查询中出现的顺序排序。
     * 最后，它将查询中未提到的字段添加到排序后的列表末尾。
     * @param {*} keys
     * @param {*} userQuery
     */
    sortKeysByUserQuery(keys, userQuery) {
      // 创建一个映射，将所有可能的中文标签（包括同义词）映射到对应的键
      const labelToKeyMap = new Map();
      keys.forEach((key) => {
        const config = labelConfig[key];
        if (config) {
          labelToKeyMap.set(config.default.toLowerCase(), key);
          config.synonyms.forEach((synonym) =>
            labelToKeyMap.set(synonym.toLowerCase(), key)
          );
        }
      });
      // 在用户查询中找到的标签
      const foundLabels = Array.from(labelToKeyMap.keys())
        .filter((label) => userQuery.toLowerCase().includes(label))
        .sort(
          (a, b) =>
            userQuery.toLowerCase().indexOf(a) -
            userQuery.toLowerCase().indexOf(b)
        );
      // 根据在查询中找到的标签顺序排序键
      const sortedKeys = foundLabels.map((label) => labelToKeyMap.get(label));
      // 添加查询中未提到的键
      keys.forEach((key) => {
        if (!sortedKeys.includes(key)) {
          sortedKeys.push(key);
        }
      });
      return sortedKeys;
    },
    // 发送后端请求，获取查询最热门的案例
    getTopList() {
      this.$axios({
        url: "http://121.41.97.114:5001/topk",
        method: "GET",
        // 10s
        timeout: 20000,
        // data: {
        //   input: msg,
        // },
        headers: {
          "Content-Type": "application/json",
        },
      })
        .then((response) => {
          console.log(response);
          const data = response.data;
          if (
            data.Code !== 200 ||
            data.Code === undefined ||
            typeof data.data === "string"
          ) {
            this.$message({
              message: "无法理解...",
              type: "warning",
              duration: 2000,
            });
          } else {
            this.topList = response.data.data;
            // 其他处理
          }
        })
        .catch((error) => {
          this.$message({
            message: "网络连接超时，请联系管理员",
            type: "error",
          });
          console.error(error);
          console.log("请求超时");
        });
    },
    handleTopClick(row) {
      this.inputMessage = row; // 将点击的查询内容赋值给输入框
    },
    /**
     * 添加消息到聊天页面,并调用接口
     * @param {*} content
     * @param {*} role self/机器人
     */
    addMessageToChat(content, role) {
      const message = {
        id: `msg-${Date.now()}`, // 确保唯一性
        content: content,
        role: role,
        type: "text",
      };
      // 更新消息列表
      this.infoList.push(message);
      this.$nextTick(() => {
        this.inputMessage = "";
        this.scrollToBottom(); // 更新完成后滚动到底部
      });
    },
    /**
     * 添加表格到聊天页面
     * @param {*} tableHeader 表头
     * @param {*} row 数据
     * @param {*} role self、机器人
     * @param sql  sql
     * @param sql  similarQuery 先请求到猜你想问的数据
     *
     */
    //表格
    addTableToChat({
      tableHeader = [], // 表头
      row = [], // 数据行
      role = "user", // 角色
      sql = "", // SQL语句
      msg = "", // 消息内容
      tableType = "type1", //使用哪一个表格组件
      similarQuery = [], // 关联查询
      ...otherProps // 扩展参数
    } = {}) {
      const message = {
        id: `msg-${Date.now()}`, // 确保唯一性
        content: msg,
        role: role,
        type: "table",
        tableType: tableType,
        columns: tableHeader,
        tableData: row,
        msg: "暂无数据",
        hasSQL: true || this.pageType === "0", // 示例逻辑
        isShowSQL: false,
        sqlString: sql,
        // 将自定义属性展开到message对象中
        ...otherProps,
      };
      // 更新消息列表
      this.infoList.push(message);
      this.$nextTick(() => {
        // 清空
        this.inputMessage = "";
        this.scrollToBottom(); // 更新完成后滚动到底部
      });
    },
    // ====================语言听写功能===========================
    recordReady() {
      console.info("按钮就绪!");
    },
    recordStart() {
      console.info("录音开始");
    },
    showResult(text) {
      // 如果需要中间结果，这个可以返回中间结果。我这里关闭了。只提供了最后结果。
      console.info("收到识别结果：", text);
    },
    recordStop() {
      console.info("录音结束");
    },
    recordNoResult() {
      // 录音识别完成，但无识别结果
      console.info("没有录到什么，请重试");
    },
    recordComplete(text) {
      console.info("识别完成! 最终结果：", text);
    },
    recordFailed(error) {
      console.info("识别失败，错误栈：", error);
    },
    //============================================》

    goBack() {
      console.log("go back");
    },
  // 发送消息的按钮
  async sendMessage() {
      if (!this.inputMessage.trim()) {
        this.$message({
          message: "输入消息不能为空！！！",
          type: "warning",
        });
        return;
      }

      // 收录上一次查询信息
     this.OldMessage=this.NewMessage;
     // 临时记录当前信息用于展示子图
     this.temp_graph =this.inputMessage



      const userMessage = {
        content: this.inputMessage,
        role: "self", // 标识 —— 客户端发出
      };

      this.infoList.push(userMessage);
      // 调用不同的后端
      switch (this.inputMessage.charAt(0)) {
        case "@":
          // 新版本后端
          this.handler_2(this.inputMessage);
          break;

          case "$":
      // 使用旧接口获取数据 
      this.handleQuery(); // 判断是否继续查询
 
     
      break;

        default:
          // 远程处理，老版本后端
          this.handler1(this.inputMessage);
          break;
      }
      // this.handler1(this.inputMessage);
      this.$nextTick(() => {
        // 清空
        this.inputMessage = "";
        this.scrollToBottom(); // 更新完成后滚动到底部
      });
    },
    /**
     * submit 常规查询：处理数据
     * @param data 后端返回的数据
     * @param msg 用户的常规查询
     */
    process_sub_res(data, msg) {
      // 数据处理
      const result = data.data;
      const row = result.result;
      const tableHeader = this.processTableData(result.result, msg);
      console.log("表头：", tableHeader);

      const sql_list = result.sql_list;
      this.sqlList = sql_list;
      const sqlString = sql_list.join("\n");

      // 对于number，统一保留小数点后2位
      const tableData = formatNumberArray(row);

      // 表头和数据中添加上下文信息 unshift/push
      tableHeader.unshift({
        field: "key_word",
        key: "key_word",
        title: "查询场景",
        align: "center",
      });

      // 为每个对象添加 key_word
      const key_word = result.keyword_array;

      // 获取所有表头的 title 字段值，形成一个数组
      const titleArray = tableHeader.map((header) => header.title);

      // 过滤掉 keyword_array 中已经在 titleArray 中的关键字
      const filteredKeywords = key_word.filter(
        (keyword) => !titleArray.includes(keyword)
      );

      // 根据表格数据转换为图数据
      const graph = this.tableToGraph(tableData, filteredKeywords);
      console.log("图数据", graph);
      this.graph_list = graph;
      this.graphKey += 1; // 强制刷新组件

      // 表格数据补充
      tableData.forEach((item) => {
        item.key_word = filteredKeywords.join(",");
      });
      console.log("表格数据", tableData);
      console.log("表格表头", tableHeader);

      this.addTableToChat({
        tableHeader: tableHeader,
        row: tableData,
        role: "机器人",
        sql: sqlString,
        msg: msg,
      });
    },
   
  },
};
</script>
  
<style scoped>
.el-container {
  flex: 1;
  display: flex;
  overflow: hidden;
  height: 100%;
  /* margin-bottom: 40px; */
}
.layout-container {
  height: 100vh;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

/* 页面三部份之一aside */
.aside {
  background-color: #ffffff;
  color: #333;
  text-align: center;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  box-shadow: 2px 2px 5px 2px rgba(0, 0, 0, 0.1);

  padding: 20px;
  overflow: auto;
  margin: 0.5px; /* 添加外边距来检查阴影 */
}
/* 图的样式 */
.graph {
  margin-top: 10px;
  margin-bottom: 10px;
  height: 80%;
}
/* 页面三部份之一main  */
.el-main {
  background-color: #ffffff;
  color: #333;
  text-align: center;
  height: calc(100% - 160px);
  flex: 1;
  overflow-y: auto;
  padding: 20px;
  box-shadow: 2px 2px 5px 2px rgba(0, 0, 0, 0.1);
  margin: 0.5px; /* 添加外边距来检查阴影 */
}
.scrollable-content {
  overflow-y: auto; /*允许上下滚动 */
}

.el-header,
.el-footer {
  background-color: #fff;
  color: #333;
  text-align: center;
  width: 100%;
  line-height: 40px;
  flex-shrink: 0;
  box-shadow: 2px 2px 5px 2px rgba(0, 0, 0, 0.1);

  margin: 0.5px; /* 添加外边距来检查阴影 */
}

/* 让 el-header 使用 flex 布局 */
.el-header {
  display: flex;
  justify-content: space-between; /* 子元素两端对齐 */
  align-items: center; /* 子元素垂直居中 */
  padding: 10px; /* 内边距 */
  margin: 0.5px; /* 添加外边距来检查阴影 */
}

/* 设置按钮的位置*/
.setting-dropdown {
  left: -150px;
}
/*设置按钮 */
.setting-button {
  height: 100%; /* 设置按钮高度为 100%，与父容器一致 */
  display: flex;
  align-items: center; /* 按钮内部内容垂直居中 */
}
/*  */
.fixed-header {
  position: sticky;
  top: 0;
  z-index: 10; /* 确保在其他内容上方 */
  background: #f0f2f5; /* 设置背景色 */
}

.fixed-footer {
  position: sticky;
  bottom: 0;
  z-index: 10;
  /* 确保在其他内容上方 */
  /* 设置背景色 */
  display: flex; /* 使用flex布局 */
  justify-content: space-between; /* 使内容在两端对齐 */
  align-items: center; /* 垂直居中对齐 */
  padding: 10px; /* 为 footer 添加适当的内边距 */
}

/*sql下拉框 */
.display {
  margin-bottom: 20px;
  width: 80%;
  right: -20px;
  align-self: center;
  height: 40px;
  transform: translateX(-20px);
}
/*aside底部容器 放头像姓名一类 */
.aside-bottom-box {
  background-color: #ddd;
  padding: 40px;
  border-radius: 5px;
  bottom: 0;
  position: relative;
  left: 50%;
  top: 300px;
  transform: translateX(-50%);
  width: 220px;
  height: 100px;
}
/*发送或接受的信息框 */
.chat-message {
  padding: 10px;
  margin: 15px;
  border-radius: 5px;
  flex-grow: 1;
}
/*main两边留白  chat-messages*/
.main-content {
  width: 80%;
  margin: 0 auto;
}
/*头像框 */
.avatar-container {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  overflow: hidden;
}
/*文本输入框 */
.input-area {
  display: flex; /* 使用 flexbox 布局 */
  align-items: center; /* 垂直居中对齐 */
  border-radius: 10px;
  width: 100%; /* 设置宽度 */
  margin: 0 auto; /* 让文本输入框水平居中 */
}
/* 语言输入 语音图像的位置为绝对定位 */
.voice-input-button-wrapper {
  width: 42px;
  height: 42px;
  /* 去掉外边距 margin: 0; */
  margin-left: 50px;
  margin-right: 20px;
  background-color: mediumpurple;
  border-radius: 50%;
  z-index: 11;
  /* 根据实际情况调整 right 的值 */
  /* position: absolute;
  right: 1090px; 
  transform: translateY(-50%); */
  top: 50%;
}
/*回复框 */
.custom-response {
  font-weight: bold;
  color: #428bca;
}
/*裁剪图片进头像 */
.avatar-image {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/*--信息框样式结束 */

/* ----------------------------------------------------------- */
/* Dialog styles */
.content {
  overflow: hidden;
}

.content-info {
  height: 100%;
  overflow-y: auto;
}

/* Information */
.content .content-info .content-list .content-li {
  clear: both;
  overflow: hidden;
}

.left-info {
  clear: both;
  margin: 20px 20px;
}

.left-info .myhead {
  float: left;
  width: 88px;
  height: 88px;
}

.left-info .myinfo {
  display: block;
  float: left;
  background: #75c475;
  /* max-width: 690px; */
  /* max-width: 90%; */
  margin-top: 10px;
  margin-left: 20px;
  padding: 10px 18px;
  border-radius: 20px;
}

.left-info::after {
  content: "";
  clear: both;
  display: block;
  height: 0;
  visibility: hidden;
}

.right-info {
  clear: both;
  margin: 10px 20px;
}

.right-info .myinfo {
  display: block;
  float: right;
  background: #efefef;
  max-width: 500px;
  margin-top: 10px;
  margin-right: 20px;
  padding: 10px 18px;
  border-radius: 20px;
}

.right-info .myhead {
  float: right;
  width: 88px;
  height: 88px;
}

.right-info::after {
  content: "";
  clear: both;
  display: block;
  height: 0;
  visibility: hidden;
}
.empty-data {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 200px;
  width: 100%;
  color: #666;
  font-size: 16px;
  border: 1px solid #eee;
  border-top: 0;
}
.case-list-scroll {
  max-height: calc(70vh - 100rpx);
}

/*组件的位置 */
.reply-container {
  position: relative;
  top: 100%;
  margin-left: -305px; /* 根据实际情况调整负值大小 */
}
</style>